'''
Created on 2009-11-9

@author: Madlee
'''
import wx
import wx.xrc  as  xrc
import kuai.kan.resource as rc

BASIC_INPUT_DIALOG_RC = r"""<?xml version="1.0" encoding="UTF-8"?>
<resource>
  <object class="wxDialog" name="BasicInputDialog">
    <object class="wxFlexGridSizer">
      <object class="sizeritem">
        <object class="wxPanel" name="ID_MAIN_PANE"/>
        <flag>wxALL|wxEXPAND</flag>
        <border>5</border>
      </object>
      <object class="sizeritem">
        <object class="wxBoxSizer">
          <object class="sizeritem">
            <object class="wxButton" name="wxID_OK"/>
            <flag>wxLEFT|wxRIGHT</flag>
            <border>5</border>
          </object>
          <object class="sizeritem">
            <object class="wxButton" name="wxID_CANCEL"/>
            <flag>wxLEFT|wxRIGHT</flag>
            <border>5</border>
          </object>
          <orient>wxHORIZONTAL</orient>
        </object>
        <flag>wxBOTTOM|wxALIGN_CENTRE</flag>
        <border>5</border>
      </object>
      <cols>1</cols>
      <rows>2</rows>
      <vgap>5</vgap>
      <hgap>5</hgap>
      <growablecols>0</growablecols>
      <growablerows>0</growablerows>
    </object>
    <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
  </object>
</resource>
"""


def get_frame(component):
    while component is not None:
        if isinstance(component, wx.Frame) or isinstance(component, wx.Dialog):
            break
        else:
            component = component.GetParent()
    return component

def show_error(err, parent=None):
    parent = get_frame(parent)
    return wx.MessageBox(str(err), rc.S_ERROR_CAPTION, wx.OK | wx.ICON_ERROR, parent);

def init_panel(self, parent, rcid, default, *args, **kwargs):
    try:
        res = wx.GetApp().res
    except:
        res = xrc.EmptyXmlResource()
        res.LoadFromString(default)
    pre = wx.PrePanel()
    res.LoadOnPanel(pre, parent, rcid)
    self.PostCreate(pre)
    BasicInputInterface.__init__(self, parent, *args, **kwargs)

class BasicInputDialog(wx.Dialog):
    def __init__(self, owner):
        try:
            res = wx.GetApp().res
        except:
            res = xrc.EmptyXmlResource()
            res.LoadFromString(BASIC_INPUT_DIALOG_RC)
        pre = wx.PreDialog()
        res.LoadOnDialog(pre, owner, "BasicInputDialog")
        self.PostCreate(pre)
        
def show_in_dialog(panel, title, owner, pref=None, *args, **kwargs):
    owner = get_frame(owner)
    dlg = BasicInputDialog(owner)
     
    dlg.SetTitle(title)
    pane = dlg.GetChildren()[0]
    box = wx.BoxSizer(wx.HORIZONTAL)
    pane.SetSizer(box)
    panel = panel(pane, *args, **kwargs)
    data = panel.load_pref({}, pref)
    panel.setup(data)
    box.Add(panel, 1, wx.EXPAND)
    pane.Fit()
    dlg.Fit()
    result = dlg.ShowModal()
    return panel, result
  

def show_input_dialog(panel, title, owner, pref=None, *args, **kwargs):
    panel, result = show_in_dialog(panel, title, owner, *args, **kwargs)
    if result == wx.ID_OK:
        return panel.collect({})
    else:
        return None

def show_and_run(panel, title, owner=None, pref=None, *args, **kwargs):
    panel, result = show_in_dialog(panel, title, owner, *args, **kwargs)
    if result == wx.ID_OK:
        data = panel.collect({})
        if pref:
            panel.save_pref(pref, data)
        return panel.execute(data)
    else:
        return None
    
def show_panel_in_main(panel, title, pref, *args, **kwargs):
    app = wx.PySimpleApp()
    return show_and_run(panel, title, None, pref, *args, **kwargs)

class BasicInputPanelInterface:
    """This is the interface for the panels in the input dialog. """
    
    def setup(self, data):
        """This mehtod change the data in the panel before it is show."""
        pass
    
    def check(self):
        """This method check the input data in the panel when the user 
press OK button. """
        pass
    
    def collect(self, data):
        """This function try to collect all input data. You should put your 
check code in the check method and should never raise exception in this 
method.
@param data: The default data. It is suggested that save the modified data into 
this param and return it directly.
@return The collected data
@throws Error Message if the input data is not correct."""
        return data
    
    def load_pref(self, data, pref):
        """This function try to collect the init data from Preferences. If the data is 
not existed in the Preferences, it should return the default settings. All the
default data and collected data should pack into a dictionary and return to the
caller. The default function do nothing and return the data directly.
@param data: Default parameters setup by the caller. It should keep 
unchanged if you do not read from pref. And you should assign the 
missing default data if the are not in it.
@param pref: The Preferences to collect input data.
@return The init data"""
        return data
    
    def save_pref(self, pref, data):
        """This function try to collect the init data from Preferences. If the data is 
not existed in the Preferences, it should return the default settings. All the
default data and collected data should pack into a dictionary and return to the
caller. The default function do nothing and return the data directly.
@param data: Default parameters setup by the caller. It should keep 
unchanged if you do not read from pref. And you should assign the 
missing default data if the are not in it.
@param pref: The Preferences to collect input data.
@return The init data"""
        pass
    
    def execute(self, data):
        return data
    
    